package net.crazyadam.activity;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import com.chance.platform.common.tablestruct.SoundLocMode;
import com.chance.platform.common.tools.Constants;
import com.chance.platform.mode.NeighborInfo;
import com.chance.platform.service.CCIRegisterBCR;
import com.chance.platform.service.CCIService;
import net.crazyadam.R;
import net.crazyadam.audio.DopplerAnalyser;
import net.crazyadam.audio.DopplerPlayer;

import java.util.*;

public abstract class DopplerActivity extends Activity {
    protected static double receivableRate = 0.9;//90%用户准备好 ，则开始甩动。
    protected static long timeout = 4000;//4k ms
    protected CCIService service; //与服务器间通信操作
    private DopplerMsgReceiver receiver; //处理与服务器通信的数据接收
    private CCIRegisterBCR register;
    private DopplerPlayer player;//高频声音播放器
    private DopplerAnalyser analyser; //声音接收处理
    private float normalWidth;//主动方甩动前的频宽
    protected Set<String> neighbors;//邻居id列表
    private Set<Integer> readyList;//
    private SortedMap<Integer, Float> rankings;//最后排名列表
    private long timeStart;//timeout start

    /**
     * 开启服务
     *
     * @throws RemoteException
     */
    protected void start(){
        try {
        player = new DopplerPlayer(this, R.raw.audio18k);
        player.start();
        neighbors = new HashSet<String>();
        neighbors.add("16844516"); //TODO remove this line
        neighbors.add("16844517"); //TODO remove this line
//        neighbors.add("16844518"); //TODO remove this line
        if(null!=service){
            //TODO to uncomment
        /*for (NeighborInfo n : service.CCIGetNebInfo()) {
            neighbors.add(Integer.toString(n.getId()));
        }*/
            service.CCISoundLocStart(new LinkedList<String>(neighbors));
        }
        rankings = new TreeMap<Integer, Float>();
        readyList = new HashSet<Integer>();
        timeStart = System.currentTimeMillis();
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    /**
     * 接收端准备好后开始甩动
     */
    protected abstract void doWhenAllReady();

    /**
     * 结束服务
     *
     */
    protected void stop() {
        if(null!=service)
            try {
                service.CCISoundLocStop(new LinkedList<String>(neighbors));
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        if(null!=player)
            player.stop();
    }

    /**
     * 返回排序结果后，处理显示。
     *
     * @param resultList
     */
    protected abstract void doAfterGetAllResults(Map<Integer, Float> resultList);

    /**
     * 测出甩动前频宽后，向服务器返回ready
     *
     * @throws RemoteException
     * @throws InterruptedException
     */
    protected void toBeReady(int fromUser) throws RemoteException, InterruptedException {
        analyser = new DopplerAnalyser(this);
        analyser.start();
        Thread.sleep(1100);
        normalWidth = analyser.stop();//测出甩动前频谱宽度
        analyser.start();
        service.CCISoundLocStartReady(fromUser);//向服务器返回ready
    }

    /**
     * 讲测出的频偏大小发给服务器
     *
     * @throws RemoteException
     */
    public void stopAndSendResult(int fromUser) throws RemoteException {
        float maxWidth = analyser.stop();
        service.CCISoundLocStopResult(fromUser, maxWidth - normalWidth);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        receiver = new DopplerMsgReceiver(this);
        register = new CCIRegisterBCR(this);
        //注册绑定服务
        register.CCIRegisterSoundLocMsgBCR(receiver, Constants.CHANCE_INTERNAL_APPID);
        bindService(new Intent("com.chance.platform.service.service_action"), connection, Context.BIND_AUTO_CREATE);
        super.onCreate(savedInstanceState);
    }

    @Override
    public void onDestroy() {
        if (null != connection)
            unbindService(connection);
        if (null != receiver)
            register.CCIUnRegisterSoundLocMsgBCR(receiver);
        if(null!=player)
            player.stop();
        super.onDestroy();
    }

    private ServiceConnection connection = new ServiceConnection() {

        @Override
        public void onServiceDisconnected(ComponentName name) {
            service = null;
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            DopplerActivity.this.service = CCIService.Stub.asInterface(service);
        }
    };

    /**
     * 服务器返回，fromUser已准备就绪
     *
     * @param fromUser 反馈用户的Id
     */
    public void readySet(Integer fromUser) {//TODO int may not be an unique key for map
        if (0 != fromUser)
            readyList.add(fromUser);
        if (readyList.size() == neighbors.size() || isTimeOut()) {
            doWhenAllReady();
            timeStart = System.currentTimeMillis();
        }

    }

    private boolean isTimeOut() {
        return timeout < System.currentTimeMillis() - this.timeStart;
    }

    public void resultSet(SoundLocMode mode) {
        rankings.put(mode.getUID(), mode.getStrength());
        if (readyList.size() == neighbors.size() || isTimeOut()) {
            doAfterGetAllResults(rankings);
        }
    }
}
